<?php
/**
 * User: hjd-yao
 * Date: 2018/11/21
 * Time: 11:52
 */

namespace App\Helpers;


class SelfRoutes
{
    private static $_allRoutes;
    private $routes;
    private $groupName;

    public function __construct()
    {
        self::$_allRoutes = app('routes')->getRoutes();
        $this->groupName = config('app.backend_name');
    }

    public static function make()
    {
        return new static();
    }

    public function setGroupName($group_name)
    {
        $this->groupName = $group_name;
        return $this;
    }

    public function checkSameRoutesName()
    {
        $name = '';
        $controller = '';
        foreach (self::$_allRoutes as $key=>$route){
            $route = collect($route)->toArray();

            if(isset($route['action']['as'])){
                if($name==$route['action']['as']&&($controller&&$controller != $route['action']['controller'])){
                    throw new \ErrorException('路由别名:'.$name.'出现重复');
                }
                $name = $route['action']['as'];
                $controller = $route['action']['controller'];
            }
        }
    }

    public function setRoutes($all = true)
    {
        $routes = self::$_allRoutes;
        $path = [];
        foreach ($routes as $k=>$value){
            $value = collect($value)->toArray();
            if((strpos($value['uri'],$this->groupName)===0)&&isset($value['action']['controller'])){
                if($value['action']['as'] == 'b_Login_logout'){
                    continue;
                }
                $class = str2arr($value['action']['controller'],'@');
                if(class_exists($class[0])&&method_exists($class[0],$class[1])
                    &&in_array('CheckIsLogin',$value['action']['middleware'])
                ){
                    if (preg_match('/\{[^\?]*?\}/', $value['uri'])) {
                        $item['is_allow_menu'] = 0;
                        $item['method'] = in_array(strtoupper('post'),$value['methods'])?'POST':$value['methods'][0];
                    }else{
                        $item['method'] = in_array(strtoupper('get'),$value['methods'])?'GET':$value['methods'][0];
                        $item['is_allow_menu'] = $item['method'] == 'GET'?1:0;
                    }
                    $item['uri'] = $value['uri'];
                    $space_len = strlen($value['action']['namespace'].'\\');
                    $item['controller'] = substr($value['action']['controller'],$space_len);
                    $item['namespace'] = $value['action']['namespace'];
                    $item['name'] =$value['action']['as'];
                    $item['prefix'] = $value['action']['prefix'];
                    $item['group'] = $this->handleGroup($value['action']['prefix']);
                    $item['middleware'] = arr2str($value['action']['middleware']);
                    $item['title'] = $this->getDocComment($value['action']['controller'])?:$item['name'];
                    $path[] = $item;
                }
            }
        }
        $this->routes = $path;
       // dd($this->routes);
        return $this;
    }

    private function handleGroup($val)
    {
        $prefix_arr = str2arr('/'.$val,'/');
        $prefix = $prefix_arr[array_search($this->groupName,$prefix_arr)+1];

        return $prefix?:'user';
    }

    public function getActionGroup($action){
        $routes = array_column($this->routes,null,'name');
        if(!$routes){
            throw  new \ErrorException('路由异常');
        }
        return $routes[$action]['group']?:'home';
    }

    /**
     * @title 对路由进行分组
     * @return $this
     */
    public function groupRoutes()
    {
        $path = [];
        $group = '';
        foreach ($this->routes as $value){
            if (isset($value['prefix'])){
                $prefix = $this->handleGroup($value['prefix']);
                if(!$group||$group != $prefix){
                    $group = $prefix;
                }
                $path[$group][] = $value;
            }

        }
        return $path;
    }

    public function getRoutes()
    {
        return $this->routes;
    }

    public function getAllNames()
    {
        return array_column($this->routes,'name');
    }

    public function getAllControllers()
    {
        return array_column($this->routes,'controller','name');
    }

    public function filter(array $keys)
    {
        foreach ($this->routes as &$route){
            foreach ($route as $key=>$val){
                if (!in_array($key,$keys)){
                    unset($route[$key]);
                }
            }
        }
        return $this;
    }

    public function filterByKey($field,$value)
    {
        foreach ($this->routes as $key=>$route){

            if(isset($route[$field])&&$route[$field]!=$value){
                unset($this->routes[$key]);
            }
        }
        return $this;
    }

    public function getAllInfo($key= null)
    {
        return array_column($this->routes,$key,'name');
    }

    public function getDocComment($controller)
    {
        $class = str2arr($controller,'@');
        $func = new \ReflectionMethod(new $class[0],$class[1]);
        if($func->getDocComment()){
            $doc = $func->getDocComment();
            if(preg_match('/@title(.*?)\r\n/',$doc,$doc)&&isset($doc[1])){
               return $doc[1];
            }
        }
        return false;
    }
}